package com.ruoyi.wechat.ws;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.wechat.domain.OnlineService;
import com.ruoyi.wechat.service.impl.OnlineServiceServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * WebSocket服务端代码
 *  接收消息:{"senderId":"发送者userId，可以为空","receiverId":"接收者userId，可以为空","content":"消息，不为空"}
 *  访问路径：ws://127.0.0.1:8080/chat/{token}
 */
@ServerEndpoint(value = "/chat/{token}")
@Component
public class WebSocketServer {
    /**存放所有在线的客户 */
    private static Map<String , Session> onlineCampUserMap = new ConcurrentHashMap<>();
    /** 存放所有在线的客服  */
    private static Map<String , Session> onlineSystemUserMap = new ConcurrentHashMap<>();

    /** 连接userId和连接会话  */
    private String userId;
    /** 会话对象   */
    private Session session;
    /** 注入在线客服消息表的业务层 */
   private static OnlineServiceServiceImpl onlineServiceService;
    @Autowired
    public void setOnlineService(OnlineServiceServiceImpl onlineService) {
        WebSocketServer.onlineServiceService = onlineService;
    }
    /** 注入token业务层 */
    private static TokenService tokenService;
    @Autowired
    public void  setTokenService(TokenService tokenService) {
        WebSocketServer.tokenService = tokenService;
    }
    /**
     * 连接建立成功调用的方法。由前端<code>new WebSocket</code>触发
     *
     * @param token 每次页面建立连接时传入到服务端的id，比如用户id等。可以自定义
     * @param session 某个客户端的连接会话，需要通过它来给客户端发送消息
     */
    @OnOpen
    public void onOpen(@PathParam("token") String token, Session session){
        //获取登录用户
        LoginUser loginUser = tokenService.getLoginUser(token);
        //判断是系统用户(客服)还是微信小程序用户
        if(loginUser.getUserId() == 100L){
            //微信小程序用户
            this.userId = loginUser.getUser().getNickName();
            /**
             * 新建立的连接，加入到map集合中
             */
            onlineCampUserMap.put(userId,session);
        }else{
            this.userId = loginUser.getUserId()+"";
            /**
             * 新建立的连接，加入到map集合中
             */
            onlineSystemUserMap.put(userId,session);
        }
        this.session = session;
        System.out.println("连接建立中==> session_id="+session.getId()+",userId="+userId);
    }


    /**
     * 关闭连接
     * @param token
     * @param session
     */
    @OnClose
    public void onClose(@PathParam("token")String token, Session session){
        //获取登录用户
        LoginUser loginUser = tokenService.getLoginUser(token);
        //判断是系统用户(客服)还是微信小程序用户
        if(loginUser.getUserId() == 100L){
            //微信小程序用户
            this.userId = loginUser.getUser().getNickName();
            /**
             * 新建立的连接，加入到map集合中
             */
            onlineCampUserMap.remove(userId);
        }else{
            this.userId = loginUser.getUserId()+"";
            /**
             * 新建立的连接，加入到map集合中
             */
            onlineSystemUserMap.remove(userId);
        }

        System.out.println("连接成功关闭,userId="+userId);
    }

    /**
     * 接收消息:{"senderId":"发送者userId，可以为空","receiverId":"接收者userId，可以为空","content":"内容"}
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(@PathParam("token")String token,String message,Session session){
        System.out.println("接收消息："+message);
        OnlineService onlineService = new OnlineService();
        //将消息存储到数据库
        if (message.indexOf("{")==0 && message.lastIndexOf("}")==(message.length()-1)) {
            onlineService = JSONObject.parseObject(message, OnlineService.class);
        }else {
            onlineService.setContent(message);
        }
       //设置消息已读
        onlineService.setState("1");
        //将消息转发到接收者
        //获取登录用户
        LoginUser loginUser = tokenService.getLoginUser(token);
        //判断是系统用户(客服)还是微信小程序用户
        if(loginUser.getUserId() == 100L){
            //设置消息发生着
            onlineService.setSenderId(loginUser.getUser().getNickName());
           //消息的发送者是：微信小程序用户，将消息推送给客服
            //获取消息的接收者
            String receiverId = onlineService.getReceiverId();
            if (!StringUtils.isBlank(receiverId)){
                //接收消息的session
                Session receiverSession = onlineSystemUserMap.get(receiverId);
                if (receiverSession!=null){
                    //发送消息：消息的接收者在线
                    receiverSession.getAsyncRemote().sendText(message);
                }
            }else{
                //没有客服在线
                if (onlineSystemUserMap.size()<=0){
                    onlineService.setState("0");//未读
                    session.getAsyncRemote().sendText("{\"content\":\"系统消息：暂无客服在线\"}");
                }else{
                    //获取消息的发送者：消息的接收者不在线
                    Set<String> keys = onlineSystemUserMap.keySet();
                    for (String key :keys ) {
                        Session receiverSession = onlineSystemUserMap.get(key);
                        onlineService.setReceiverId(key);
                        //发送消息：消息的接收者在线
                        receiverSession.getAsyncRemote().sendText(JSONObject.toJSONString(onlineService));
                        break;
                    }
                }
            }
        }else{
            //消息的发送者是：系统用户，客服，将消息推送给小程序用户
            //获取消息的接收者
            String receiverId = onlineService.getReceiverId();
            //接收消息的session
            Session receiverSession = onlineCampUserMap.get(receiverId);
            if (receiverSession!=null){
                //发送消息：消息的接收者在线
                receiverSession.getAsyncRemote().sendText(onlineService.getContent());
            }else{
                onlineService.setState("0");//未读
                session.getAsyncRemote().sendText("{\"content\":\"系统消息：用户不在线\"}");
            }
        }
        //新增在线消息
        onlineServiceService.insertOnlineService(onlineService);
    }

    /**
     * 发生错误调用的方法
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session,Throwable error){
        System.out.println("WebSocket发送错误，错误信息为："+error.getMessage());
        error.printStackTrace();
    }


    /**
     * 发送单个消息
     * @param userId 用户id，消息
     * @param message 消息
     */
    public void sendToOne(String userId, String message) {
        /**
         * 判断发送者是否在线
         */
        Session toSession = onlineCampUserMap.get(userId);
        if (toSession==null){
            System.out.println("客户端"+userId+"不在线。");
            return;
        }
        //异步发送消息
        System.out.println("客户端发送给服务端的消息："+message+", session_id="+session.getId()+",userId="+userId);
        toSession.getAsyncRemote().sendText(message);
    }
    /**
     * 群发消息
     * @param message 消息
     */
    public void sendToAll( String message) {
        onlineCampUserMap.forEach((onlineUserId,toSession)->{
            //排除自己
            if (!userId.equalsIgnoreCase(onlineUserId)){
                System.out.println("群发消息："+message);
                toSession.getAsyncRemote().sendText(message);
            }
        });
    }
}



